# !/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/1/30 9:13
# @Author  : xinyingjie
# @File    : main-dev.py
# @Description :  隧道多断面仿真拼接


from __future__ import absolute_import
from __future__ import print_function

import json
import os
import threading
import uuid
import random
import time
import asyncio
import traci.constants as tc
import sumolib
import traci
from kafka import KafkaProducer
from config.config import route_list
from util.websocketserver1 import WebSocketServer
import kafka_util
from util import sumo_utils
# from kafka_util import pre_data_queue, all_data_queue, ai_data_queue
import logging
from util.tools import calculate_distance
from config.config import GLOBAL_POLYGON_CENTER, MAX_SPEED, MIN_SPEED, CAR_DEFAULT_SPEED, TRUCK_DEFAULT_SPEED, \
    SPECIAL_DEFAULT_SPEED, erId_dict, type_change, route_list, KAFKA_HOST, SUMO_TOPIC

car_cache_info = {}
moveTo_info = {}
routeIdList = []
global_vehicles = {}
exists_list = []
slow_car_list = []

ws_server = WebSocketServer()
ws_server.start()

loop = asyncio.get_event_loop()
temp = []
type_list = [1, 3, 15, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ]
cl_list = [2, 3, 4, 6, 8, 9]
route_dict = {}
pos_dict = {}


# "G152300000000000001": {"lon": 121.363835720355738, "lat": 28.2150032304759},
def get_logger(log_type):
    # 第一步，创建一个logger
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)  # Log等级总开关
    # 第二步，创建一个handler，用于写入日志文件
    rq = str(time.strftime('%Y%m%d', time.localtime(time.time()))) + '_' + str(log_type)
    log_path = 'logs/'
    # log_path = '/opt/python' + '/logs/'
    # print('log_path', log_path)
    if not os.path.exists(log_path):
        os.mkdir(log_path)

    log_name = log_path + rq + '.log'
    logfile = log_name
    fh = logging.FileHandler(logfile)
    fh.setLevel(logging.DEBUG)  # 输出到file的log等级的开关
    # 第三步，定义handler的输出格式
    formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
    fh.setFormatter(formatter)
    # 第四步，将logger添加到handler里面
    logger.addHandler(fh)
    return logger


def main(sumo_cfg_file=None, sumo_net_file=None, gui=True):
    global global_vehicles
    sumo_net_instance = sumolib.net.readNet(sumo_net_file, withInternal=True, withLatestPrograms=True)
    sumo_utils.start_sumo(sumo_cfg_file, False, gui=False)
    # 设置所有车道的最大通行速度
    for id in traci.lane.getIDList():
        traci.lane.setMaxSpeed(id, MAX_SPEED)
    traci.polygon.add('GLOBAL_POLYGON_CENTER', GLOBAL_POLYGON_CENTER, (1, 0, 1))
    traci.polygon.subscribeContext('GLOBAL_POLYGON_CENTER',
                                   tc.CMD_GET_VEHICLE_VARIABLE, 100000,
                                   [tc.VAR_SPEED, tc.VAR_DECEL, tc.VAR_DISTANCE, tc.VAR_TYPE, tc.VAR_POSITION,
                                    tc.VAR_ROAD_ID, tc.VAR_LANE_INDEX, tc.VAR_LANE_ID, tc.VAR_ACCEL, tc.VAR_ANGLE,
                                    tc.VAR_LANE_ID, tc.VAR_ACCELERATION, tc.VAR_LANE_INDEX,
                                    tc.TRAFFICLIGHT_TYPE_STATIC, tc.VAR_WAITING_TIME])
    traci.simulation.subscribe([tc.VAR_ARRIVED_VEHICLES_NUMBER,
                                tc.VAR_ARRIVED_VEHICLES_IDS,
                                tc.VAR_DEPARTED_VEHICLES_NUMBER,
                                tc.VAR_DEPARTED_VEHICLES_IDS,
                                tc.VAR_COLLIDING_VEHICLES_NUMBER,
                                tc.VAR_COLLIDING_VEHICLES_IDS])
    # 获取虚拟设备状态kafka数据
    # threading.Thread(target=kafka_util.receive_message_of_pre_data).start()
    # threading.Thread(target=kafka_util.receive_message_of_all_data).start()
    # threading.Thread(target=kafka_util.receive_message_of_ai_data).start()
    # ws_server = WebSocketServer()
    # ws_server.start()

    # producer = KafkaProducer(bootstrap_servers=KAFKA_HOST, key_serializer=str.encode,
    #                          value_serializer=lambda x: json.dumps(x).encode('utf-8'))

    EdgeID0, Pos0, LaneIndex0 = traci.simulation.convertRoad(114.129515, 30.572173, True)
    EdgeID1, Pos1, LaneIndex1 = traci.simulation.convertRoad(114.129564, 30.572151, True)
    EdgeID2, Pos2, LaneIndex2 = traci.simulation.convertRoad(114.129584, 30.572107, True)
    pos_dict['0'] = Pos0
    pos_dict['1'] = Pos1
    pos_dict['2'] = Pos2

    # traci.route.add(str(EdgeID10),
    #                 ['-9', '-22', '-23', '-24', '-16', '-28#0', '-28#1', '-11','-4',  '-1#0', '-1#1', '-1#2',
    #                  '-1#3', '-1#4', '-10', '-19', '-5', '-17', '-21', '-13', '-29'])
    for num, route in route_list.items():
        for index, r in enumerate(route):
            traci.route.add(str(num + "_" + str(index)), r)
            print(str(num + "_" + str(index)), r)
            if num not in route_dict.keys():
                route_dict[num] = [str(num + "_" + str(index))]
            else:
                route_dict[num].append(str(num + "_" + str(index)))

    # for k, v in erId_dict.items():
    #     x, y = traci.simulation.convertGeo(v["lon"], v["lat"], fromGeo=True)
    #     EdgeIDk, Posk, LaneIndexk = traci.simulation.convertRoad(v["lon"], v["lat"], True)
    #     print("EdgeIDk", EdgeIDk)
    #     erId_dict[k]["x"] = x
    #     erId_dict[k]["y"] = y
    #     erId_dict[k]["edge"] = EdgeIDk
    #     erId_dict[k]["pos"] = Posk
    # logger = get_logger("simulation")
    startSimuTime = int(time.time() * 1000)
    count = 0
    try:
        # loop = asyncio.get_event_loop()
        while (True):
            count += 1

            try:
                start_time = time.time()

                #  相机感知结果  增加仿真车
                if count % 10 == 0:
                    lane_num = str(random.randint(0, 2))
                    print("添加车辆", random.choice(route_dict[lane_num]))

                    cid = str(random.choice(cl_list)) + "_" + str(start_time)
                    traci.vehicle.add(
                        vehID=cid,
                        routeID=random.choice(route_dict[lane_num]),
                        # typeID=str(vInfo["vehicleType"]), depart='0', departPos=Pos,
                        typeID=str(random.choice(type_list)), depart='0', departPos=pos_dict[lane_num],
                        departSpeed=str(CAR_DEFAULT_SPEED))
                    traci.vehicle.setSpeed(cid, CAR_DEFAULT_SPEED)

                car_list = list()

                global_vehicles = traci.polygon.getContextSubscriptionResults('GLOBAL_POLYGON_CENTER')
                for vehicle_id, veh_info in dict(global_vehicles).items():
                    pos = veh_info[tc.VAR_POSITION]
                    longitude, latitude = sumo_utils.xyConversionlatAndLon(sumo_net_instance, pos)

                    # wait_time = veh_info[tc.VAR_WAITING_TIME]
                    # print(wait_time)
                    # if int(wait_time) > 5:
                    #     traci.vehicle.remove(vehicle_id)

                    # pos = veh_info[tc.VAR_POSITION]
                    # longitude, latitude = sumo_utils.xyConversionlatAndLon(sumo_net_instance, pos)
                    speed = veh_info[tc.VAR_SPEED]
                    # print(speed)
                    vehicle_type = veh_info[tc.VAR_TYPE]

                    # if 114.132264 < longitude < 114.134233 :
                    #     print(int(veh_info[tc.VAR_LANE_INDEX]))
                    #     if int(veh_info[tc.VAR_LANE_INDEX]) > 10:
                    #         traci.vehicle.changeLane(vehicle_id,int(veh_info[tc.VAR_LANE_INDEX])-1,1)
                    #     if int(veh_info[tc.VAR_LANE_INDEX]) < 2:
                    #         traci.vehicle.changeLane(vehicle_id,int(veh_info[tc.VAR_LANE_INDEX])+1,1)
                    #
                    # if 114.135480 >longitude > 114.134233:
                    #     traci.vehicle.setLaneChangeMode(str(vehicle_id), 0)

                    # if longitude > 114.136623:
                    #     traci.vehicle.setLaneChangeMode(str(vehicle_id), -1)
                    unlawfulMold = ""
                    if vehicle_type == "3":
                        vehicle_type = "6"
                        unlawfulMold = "0102"
                    if vehicle_type == "15":
                        vehicle_type = "3"
                        unlawfulMold = "0102"
                    if vehicle_type == "16":
                        vehicle_type = "8"
                        unlawfulMold = "0103"

                    # vehicle_type = '6'
                    car = {"id": vehicle_id, "ty": vehicle_type, "lo": longitude,
                           "la": latitude, "speed": speed,
                           "ag": veh_info[tc.VAR_ANGLE],
                           "eventType": "", "cl": vehicle_id.split("_")[0], "pl": "默A0000", "info": {},
                           "etcVehClass": int(vehicle_type),
                           "vehTradeResult": "2", "unlawfulCode": unlawfulMold, }
                    # car = {"ID": vehicle_id, "type": int(vehicle_type), "longitude": longitude,
                    #        "latitude": latitude, "speed": speed,
                    #        "courseAngle": veh_info[tc.VAR_ANGLE],
                    #        "eventType": "", "cl": "", "pl": "默A0000", "info": {}, "etcVehClass": int(vehicle_type),
                    #        "vehTradeResult": "2", }
                    # print(car)
                    car_list.append(car)
                timestamp = int(time.time() * 1000)
                result = {"participants": car_list, "msgCount": len(car_list),
                          "timeStamp": timestamp, "frameID": count}
                # print(result)
                # producer.send(SUMO_TOPIC, value=result, key="key")
                loop.run_until_complete(ws_server.broadcast(str(result).replace("'", '"')))
                traci.simulationStep()
                end_time = time.time()

                if start_time and (end_time - start_time) < 0.1:
                    # print("耗时",(end_time - start_time))
                    time.sleep(0.1 - (end_time - start_time))
                else:
                    if start_time:
                        print("单帧耗时大于0.1s", end_time - start_time)
            except Exception as e:
                traci.simulationStep()
                time.sleep(0.05)
                print(str(e))
                continue

    except Exception as e:
        print(str(e))


if __name__ == "__main__":
    sumo_net_file = r".\config\0517.net.xml"  # 路网文件
    sumo_cfg_file = r".\config\hubeiqintai.sumocfg"  # 路网文件
    logger = get_logger("simulation")
    logger.info("test")

    main(sumo_cfg_file=sumo_cfg_file, sumo_net_file=sumo_net_file)
